import { DomResult } from './types'

interface ClickOptions {
  timeout?: number
}

const DEFAULT_CLICK_OPTIONS: Required<ClickOptions> = {
  timeout: 5000, // 5秒 目标不存在等待时间
}

// 使用MutationObserver等待元素出现
const waitForElement = (selectorFn: () => Element | null, timeout: number): Promise<Element | null> => {
  return new Promise((resolve) => {
    // 先立即检查
    const immediateElement = selectorFn()
    if (immediateElement) {
      resolve(immediateElement)
      return
    }

    const observer = new MutationObserver(() => {
      const element = selectorFn()
      if (element) {
        observer.disconnect()
        resolve(element)
      }
    })

    // 开始观察
    observer.observe(document.body, {
      childList: true,
      subtree: true
    })

    // 设置超时
    const timeoutId = setTimeout(() => {
      observer.disconnect()
      resolve(selectorFn()) // 最后再检查一次
    }, timeout)

    // 清理函数
    const cleanup = () => {
      clearTimeout(timeoutId)
      observer.disconnect()
    }

    // 如果Promise被取消，清理资源
    Promise.resolve().then(() => {
      // 确保在微任务中检查，避免竞态条件
    })
  })
}

// 专门处理React点击
function triggerReactClickIfAvailable(el: Element): boolean {
  // 如果元素本身有React处理器，先尝试触发
  let key = Object.keys(el).find(p => p.startsWith('__reactFiber') || p.startsWith('__reactInternalInstance'))

  if (key) {
    const fiberNode = (el as any)[key]
    let props = fiberNode?.memoizedProps || fiberNode?.pendingProps

    if (props?.onClick) {
      triggerReactClick(el, props.onClick)
      return true
    }
  }

  // 如果元素本身没有，递归查找子元素
  const childrenWithHandler = Array.from(el.children || []).find(child => {
    const childKey = Object.keys(child).find(p => p.startsWith('__reactFiber') || p.startsWith('__reactInternalInstance'))
    if (childKey) {
      const childFiber = (child as any)[childKey]
      const childProps = childFiber?.memoizedProps || childFiber?.pendingProps
      return childProps?.onClick
    }
    return false
  })

  if (childrenWithHandler) {
    const childKey = Object.keys(childrenWithHandler).find(p => p.startsWith('__reactFiber') || p.startsWith('__reactInternalInstance'))
    const childFiber = (childrenWithHandler as any)[childKey]
    const childProps = childFiber?.memoizedProps || childFiber?.pendingProps

    triggerReactClick(childrenWithHandler, childProps.onClick)
    return true
  }

  // 如果还是没有，尝试查找所有后代元素
  const allElements = el.getElementsByTagName('*')
  for (let i = 0; i < allElements.length; i++) {
    const element = allElements[i]
    const elementKey = Object.keys(element).find(p => p.startsWith('__reactFiber') || p.startsWith('__reactInternalInstance'))

    if (elementKey) {
      const elementFiber = (element as any)[elementKey]
      const elementProps = elementFiber?.memoizedProps || elementFiber?.pendingProps

      if (elementProps?.onClick) {
        triggerReactClick(element, elementProps.onClick)
        return true
      }
    }
  }

  return false
}

// 触发普通click事件
function triggerNormalClick(element: Element): boolean {
  try {
    // 方法1: 直接调用元素的click方法 (最简单)
    if (typeof (element as any).click === 'function') {
      (element as any).click()
      return true
    }

    // 方法2: 创建并分发MouseEvent事件 (更接近真实用户点击)
    const mouseEvent = new MouseEvent('click', {
      view: unsafeWindow,
      bubbles: true,
      cancelable: true,
      composed: true
    })

    // 先尝试dispatchEvent
    const dispatched = element.dispatchEvent(mouseEvent)
    if (dispatched) {
      return true
    }

    // 方法3: 如果上述方法都失败，尝试HTMLElement的点击
    if (element instanceof HTMLElement || element instanceof SVGElement) {
      // 模拟焦点和点击
      if (typeof element.focus === 'function') {
        element.focus()
      }

      // 再次尝试click方法
      if (typeof (element as any).click === 'function') {
        (element as any).click()
        return true
      }
    }

    return false
  } catch (error) {
    console.error('普通点击失败:', error)
    return false
  }
}

interface SyntheticEvent {
  type: string
  nativeEvent: MouseEvent
  target: Element
  currentTarget: Element
  eventPhase: number
  bubbles: boolean
  cancelable: boolean
  timeStamp: number
  defaultPrevented: boolean
  isTrusted: boolean
  isDefaultPrevented: () => boolean
  isPropagationStopped: () => boolean
  persist: () => void
  preventDefault: () => void
  stopPropagation: () => void
  stopImmediatePropagation: () => void
}

// 提取出来的触发React点击的公共函数
function triggerReactClick(element: Element, onClickHandler: (event: SyntheticEvent) => void): void {
  const syntheticEvent: SyntheticEvent = {
    type: 'click',
    nativeEvent: new MouseEvent('click', {
      bubbles: true,
      cancelable: true,
      view: unsafeWindow
    }),
    target: element,
    currentTarget: element,
    eventPhase: 3, // Bubbling phase
    bubbles: true,
    cancelable: true,
    timeStamp: Date.now(),
    defaultPrevented: false,
    isTrusted: false,
    isDefaultPrevented: () => false,
    isPropagationStopped: () => false,
    persist: () => { },
    preventDefault: function (this: SyntheticEvent) {
      this.defaultPrevented = true
      if (this.nativeEvent.preventDefault) {
        this.nativeEvent.preventDefault()
      }
    },
    stopPropagation: function (this: SyntheticEvent) {
      (this as any).isPropagationStopped = () => true
      if (this.nativeEvent.stopPropagation) {
        this.nativeEvent.stopPropagation()
      }
    },
    stopImmediatePropagation: function (this: SyntheticEvent) {
      (this as any).isPropagationStopped = () => true
      if (this.nativeEvent.stopImmediatePropagation) {
        this.nativeEvent.stopImmediatePropagation()
      }
    }
  }

  onClickHandler(syntheticEvent)
}

export const $reactClick = (el: Element): boolean => {
  try {
    // 首先尝试React点击
    if (triggerReactClickIfAvailable(el)) {
      return true
    }

    // 如果React点击失败，回退到普通click事件
    return triggerNormalClick(el)
  } catch (error) {
    console.error('点击失败:', error)
    return false
  }
}

// 单独导出普通点击函数，方便单独使用
export const $normalClick = triggerNormalClick

// 创建选择器函数的辅助函数
export const createSelector = (selector: string): (() => Element | null) => {
  return () => document.querySelector(selector)
}

export const $click = async (
  selectorFn: string | (() => Element | null),
  options: ClickOptions = {}
): Promise<DomResult> => {
  const { timeout } = { ...DEFAULT_CLICK_OPTIONS, ...options }

  try {
    // 统一处理选择器函数
    const elementSelector = typeof selectorFn === 'string'
      ? createSelector(selectorFn)
      : selectorFn

    // 1. 等待元素出现
    const element = await waitForElement(elementSelector, timeout)

    // 2. 如果元素不存在
    if (!element) {
      return DomResult.NOT_FOUND
    }

    // 3. 尝试点击
    try {
      const clickSuccess = $reactClick(element)
      if (clickSuccess) {
        return DomResult.SUCCESS
      } else {
        return DomResult.CLICK_ERROR
      }
    } catch (error) {
      console.error('点击操作失败:', error)
      return DomResult.CLICK_ERROR
    }

  } catch (error) {
    console.error('点击过程发生错误:', error)
    return DomResult.CLICK_ERROR
  }
}

// 新增：支持复杂条件的等待函数
export const $waitFor = (
  conditionFn: () => boolean,
  options: ClickOptions = {}
): Promise<boolean> => {
  const { timeout } = { ...DEFAULT_CLICK_OPTIONS, ...options }

  return new Promise((resolve) => {
    // 先立即检查
    if (conditionFn()) {
      resolve(true)
      return
    }

    const observer = new MutationObserver(() => {
      if (conditionFn()) {
        observer.disconnect()
        resolve(true)
      }
    })

    observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true, // 属性变化也可能影响条件
      characterData: true // 文本内容变化
    })

    setTimeout(() => {
      observer.disconnect()
      resolve(conditionFn()) // 最后检查一次
    }, timeout)
  })
}